using System;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using ClickerClimber.Models;
using ClickerClimber.Managers;
using ClickerClimber.Model;

namespace ClickerClimber
{
    public class Item : IGameObject, IGameObjectDrawable
    {
        public enum ItemState
        {
            IDLE,
            FALLING
        }

        public enum ItemType
        {
            BLUE,
            RED,
            GREEN,
            YELLOW,
            MAGENTA
        }

        public enum ItemBackgroundType
        {
            TYPE1,
            TYPE2,
            TYPE3
        }

        public enum eCellType
        {
            ITEM,
            BACKGROUND
        }

        #region members

        // This is a texture we can render.
        private Texture2D _textureItem;
        private Texture2D _textureItemHighlight;

        // Set the coordinates to draw the sprite at.
        private Vector2 _spritePosition;
        private Vector2 _spriteOffset;
        private float _width, _height;
        private Vector2 _absolutePosition;
        Vector2 _origin;

        // Store some information about the sprite's motion.
        private Vector2 _spriteSpeed;
        private float _rotation;
        private float _rotationOffset;
        private ItemType _type;
        private ItemBackgroundType _typeBackground;
        private eCellType _cellType;

        private Pair _cellPosition;

        private bool _visited;
        private bool _hasItem;
        private bool _hasBackground;
        private bool _isVisible;

        private ItemState _state;
        private float _mass;

        private bool _highlight;

        private Random _randomGenerator = new Random();

        #endregion members

        /// <summary>
        /// Initialize
        /// </summary>
        public void Initialize()
        {
            _spritePosition = Vector2.Zero;
            _spriteSpeed = new Vector2(50.0f, 50.0f);
            _visited = false;
            _cellType = eCellType.ITEM;
            _state = ItemState.IDLE;
            _rotation = 0.0f;
            _rotationOffset = _randomGenerator.Next(360);
            _origin = Vector2.Zero;
            _highlight = false;
            _isVisible = true;
        }

        /// <summary>
        /// Update
        /// </summary>
        /// <param name="gameTime"></param>
        public void Update(GameTime gameTime)
        {
            switch (_state)
            {
                case ItemState.IDLE:
                    break;
                case ItemState.FALLING:
                    UpdateGravity(gameTime);
                    break;
            }
        }

        public void LoadTextures(ContentManager content)
        {
            string textureName = GameParameters.BLUE_ITEM_TEXTURE_NAME;
            switch(_cellType)
            {
                case eCellType.ITEM:
                    switch (_type)
                    {
                        case ItemType.BLUE:
                            textureName = GameParameters.BLUE_ITEM_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        case ItemType.RED:
                            textureName = GameParameters.RED_ITEM_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        case ItemType.GREEN:
                            textureName = GameParameters.GREEN_ITEM_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_2;
                            break;
                        case ItemType.YELLOW:
                            textureName = GameParameters.YELLOW_ITEM_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        case ItemType.MAGENTA:
                            textureName = GameParameters.MAGENTA_ITEM_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_3;
                            break;
                        default:
                            break;
                    }
                    _textureItem = content.Load<Texture2D>(textureName);
                    _textureItemHighlight = content.Load<Texture2D>(textureName + "_hl");
                    _width = _textureItem.Width;
                    _height = _textureItem.Height;
                    _spriteOffset.X = _width * 0.5f;
                    _spriteOffset.Y = _height * 0.5f;
                    _origin = _spriteOffset;
                    break;
                case eCellType.BACKGROUND:
                    switch (_typeBackground)
                    {
                        case ItemBackgroundType.TYPE1:
                            textureName = GameParameters.BACKGROUND_ITEM1_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        case ItemBackgroundType.TYPE2:
                            textureName = GameParameters.BACKGROUND_ITEM2_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        case ItemBackgroundType.TYPE3:
                            textureName = GameParameters.BACKGROUND_ITEM3_TEXTURE_NAME;
                            _mass = GameParameters.GEM_MASS_1;
                            break;
                        default:
                            break;
                    }
                    _textureItem = content.Load<Texture2D>(textureName);
                    _width = _textureItem.Width;
                    _height = _textureItem.Height;
                    _spriteOffset.X = _width * 0.5f;
                    _spriteOffset.Y = _height * 0.5f;
                    _origin = _spriteOffset;
                    break;
            }
        }

        public void Draw(SpriteBatch batch)
        {
            if (_isVisible)
            {
                Color color = Color.White;
                //Color backgroundColor = new Color(255, 247, 210);
                if (_cellType == eCellType.BACKGROUND)
                {
                    color = new Color(255, 255, 255, 200);
                }
                //if (_cellType == eCellType.ITEM)
                if (_highlight)
                {
                    batch.Draw(_textureItemHighlight, GameParameters.SCROLL_OFFSET + _spritePosition - _spriteOffset, color);
                }
                else
                {
                    batch.Draw(_textureItem, GameParameters.SCROLL_OFFSET + _spritePosition - _spriteOffset, color);
                }
                //batch.Draw(_textureItem, GameParameters.SCROLL_OFFSET + _spritePosition - _spriteOffset, null, color,
                //    0.0f, _origin, 1.0f, SpriteEffects.None, 0f);
                /*else
                    batch.Draw(_textureItem, GameParameters.SCROLL_OFFSET + _spritePosition - _spriteOffset, color);
                    batch.Draw(_textureItem, GameParameters.SCROLL_OFFSET + _spritePosition - _spriteOffset, null, color,
                        _rotation + _rotationOffset, _origin, 1.0f, SpriteEffects.None, 0f);
                 */
            }
        }


        public bool IsIn(Vector2 point)
        {
            point -= GameParameters.SCROLL_OFFSET;
            if (point.X > _absolutePosition.X - _spriteOffset.X && point.X < _absolutePosition.X + _spriteOffset.X &&
                point.Y > _absolutePosition.Y - _spriteOffset.Y && point.Y < _absolutePosition.Y + _spriteOffset.Y)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void ChangeState(ItemState newState)
        {
            _state = newState;
        }

        private void UpdateGravity(GameTime gameTime)
        {
            float fallingOffsetY = 9.8f * gameTime.ElapsedGameTime.Milliseconds / 1000.0f * _mass;

            if (_spritePosition.Y + fallingOffsetY < _absolutePosition.Y)
            {
                _spritePosition.Y += fallingOffsetY;
                double angle = gameTime.TotalGameTime.Milliseconds / 100.0f;
                _rotation = (float) Math.Sin(angle);
            }
            else
            {
                _spritePosition.Y = _absolutePosition.Y;
                _state = ItemState.IDLE;
                _rotation = 0.0f;
            }
        }

        #region Properties

        public ItemType Type
        {
            get
            {
                return _type;
            }
            set
            {
                _type = value;
            }
        }

        public ItemBackgroundType TypeBackground
        {
            get
            {
                return _typeBackground;
            }
            set
            {
                _typeBackground = value;
            }
        }

        public eCellType CellType
        {
            get
            {
                return _cellType;
            }
            set
            {
                _cellType = value;
            }
        }

        public Vector2 Position
        {
            set
            {
                _spritePosition = value;
            }
            get
            {
                return _spritePosition;
            }
        }

        public Vector2 AbsolutePosition
        {
            set
            {
                _absolutePosition = value;
            }
            get
            {
                return _absolutePosition;
            }
        }

        public Vector2 Offset
        {
            set
            {
                _spriteOffset = value;
            }
            get
            {
                return _spriteOffset;
            }
        }

        public Pair CellPosition
        {
            set
            {
                _cellPosition = value;
            }
            get
            {
                return _cellPosition;
            }
        }

        public bool Visited
        {
            get
            {
                return _visited;
            }
            set
            {
                _visited = value;
            }
        }

        public int Width
        {
            get
            {
                return _textureItem.Width;
            }
        }

        public int Height
        {
            get
            {
                return _textureItem.Width;
            }
        }

        public bool HasItem
        {
            get
            {
                return _hasItem;
            }
            set
            {
                _hasItem = value;
            }
        }

        public bool HasBackground
        {
            get
            {
                return _hasBackground;
            }
            set
            {
                _hasBackground = value;
            }
        }

        public Texture2D TextureItem
        {
            get
            {
                return _textureItem;
            }
            set
            {
                _textureItem = value;
            }
        }

        public Texture2D TextureItemHightlight
        {
            get
            {
                return _textureItemHighlight;
            }
            set
            {
                _textureItemHighlight = value;
            }
        }

        public bool IsFalling
        {
            get
            {
                return _state == ItemState.FALLING;
            }
        }

        public bool Highlight
        {
            set
            {
                _highlight = value;
            }
            get
            {
                return _highlight;
            }
        }


        public bool IsVisible
        {
            set
            {
                _isVisible = value;
            }
            get
            {
                return _isVisible;
            }
        }
        #endregion Properties
    }
}